#include "Level.h"
#include "..\Managers\PhysicsManager.h"
#include "..\Managers\RenderManager.h"
#include "..\Managers\ResourceManager.h"
#include "..\rapidxml.hpp"
#include "..\Debug\DebugLog.h"
#include "..\Generic\BoolMessage.h"
#include "..\Generic\MessageSystem.h"
#include <fstream>

Level::Level(const std::string& p_filepath) : m_filepath(p_filepath)
{
	MessageSystem::getSingleton().registerSubject<Level>("play_music", this, &Level::playMusic);
}

Level::~Level(void)
{ 
	clear();
	MessageSystem::getSingleton().unregister("play_music", this);
	delete m_music;
}

void Level::loadLevel()
{
	
	std::ifstream file(m_filepath);
	if (file)
	{
		std::string xmlContent;
		std::string line;
		while (std::getline(file, line))
			xmlContent += line;

		file.close();

		std::vector<char> xmlBuffer = std::vector<char>(xmlContent.begin(), xmlContent.end());
		xmlBuffer.push_back('\0');
		rapidxml::xml_document<> doc;
		doc.parse<rapidxml::parse_no_data_nodes>(&xmlBuffer[0]);
		rapidxml::xml_node<>* root = doc.first_node();
		rapidxml::xml_node<>* data = root->first_node("tilesets");
		rapidxml::xml_node<>* tileset = data->first_node("tileset");

		m_widht = static_cast<float>(atof(root->first_attribute("width")->value()));
		m_height = static_cast<float>(atof(root->first_attribute("height")->value()));

		while (tileset)
		{
			unsigned int view = static_cast<unsigned int>(atoi(tileset->first_attribute("view")->value()));
			float layer = static_cast<float>(atof(tileset->first_attribute("layer")->value()));
			std::string filepath = "levels\\" + std::string(tileset->first_attribute("filename")->value());
			vn::TileEngine* tileEngine = RenderManager::getSingleton().getRenderEngine()->createTiles(view, filepath, layer);
			m_tiles.push_back(tileEngine);
			tileset = tileset->next_sibling();
		}

		data = root->first_node("collision");
		std::string str = "levels\\" + std::string(data->first_attribute("filename")->value());
		PhysicsManager::getSingleton().createCollision(str);
		data = root->first_node("background");
		str = data->first_attribute("spriteID")->value();
		m_bg = RenderManager::getSingleton().getRenderEngine()->createSprite(0, str);
		data = root->first_node("music");
		str = "music\\" + std::string(data->first_attribute("filepath")->value());
		m_music = ResourceManager::getSingleton().getAudioEngine()->loadMusic(str);
		m_music->setLoop(true);

		vn::Camera* camera = RenderManager::getSingleton().getRenderEngine()->getCamera("main");
		camera->setLevelSize(0.0f, 0.0f, m_widht, m_height);
		camera->setFreeMovement(false);
	}
	else
		Debug::log("ERROR: cannot open level " + m_filepath);
}

void Level::clear()
{
	if (!m_tiles.empty())
	{
		for (auto it = m_tiles.begin(); it != m_tiles.end(); it++)
		{
			RenderManager::getSingleton().getRenderEngine()->destroyTileEngine((*it));
			(*it) = nullptr;
		}
		m_tiles.clear();
	}

	if (m_bg != nullptr)
	{
		RenderManager::getSingleton().getRenderEngine()->destroySprite(m_bg);
		m_bg = nullptr;
	}
}

void Level::playMusic(const std::string& p_id, Message* p_message)
{
	BoolMessage* msg = static_cast<BoolMessage*>(p_message);
	if (msg->getValue())
		m_music->play();
	else
		m_music->stop();
}

void Level::playMusic(bool p_value)
{
	if (p_value)
		m_music->play();
	else
		m_music->stop();
}